diff options
Diffstat (limited to 'app/[lng]/evcp/(evcp)/avl/[id]/page.tsx')
| -rw-r--r-- | app/[lng]/evcp/(evcp)/avl/[id]/page.tsx | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/app/[lng]/evcp/(evcp)/avl/[id]/page.tsx b/app/[lng]/evcp/(evcp)/avl/[id]/page.tsx new file mode 100644 index 00000000..52ee7b7f --- /dev/null +++ b/app/[lng]/evcp/(evcp)/avl/[id]/page.tsx @@ -0,0 +1,106 @@ +import * as React from "react" +import { type SearchParams } from "@/types/table" +import { notFound } from "next/navigation" + +import { getValidFilters } from "@/lib/data-table" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { getAvlLists, getAvlDetail } from "@/lib/avl/service" +import { avlDetailSearchParamsCache } from "@/lib/avl/validations" +import { AvlDetailTable } from "@/lib/avl/table/avl-detail-table" +import { getAvlListById } from "@/lib/avl/service" + +interface AvlDetailPageProps { + params: Promise<{ id: string }> + searchParams: Promise<SearchParams> +} + +export default async function AvlDetailPage(props: AvlDetailPageProps) { + const { id } = await props.params + const searchParams = await props.searchParams + const search = avlDetailSearchParamsCache.parse(searchParams) + + const validFilters = getValidFilters(search.filters) + + // ID 검증 + const numericId = Number(id) + if (isNaN(numericId) || numericId <= 0) { + notFound() + } + + // AVL 리스트 정보 조회 + const avlListInfo = await getAvlListById(numericId) + if (!avlListInfo) { + notFound() + } + + const promises = Promise.all([ + getAvlDetail({ + ...search, + filters: validFilters, + avlListId: numericId, + }), + ]) + + return ( + <div className="h-screen flex flex-col"> + {/* 메인 콘텐츠 영역 */} + <div className="flex-1 overflow-hidden"> + <div className="h-full p-4 md:p-6"> + <React.Suspense + fallback={ + <DataTableSkeleton + columnCount={20} + searchableColumnCount={1} + filterableColumnCount={5} + cellWidths={[ + "50px", "60px", "120px", "120px", "150px", "130px", "130px", + "140px", "140px", "100px", "100px", "100px", "100px", "120px", + "140px", "150px", "80px", "100px", "80px", "140px", "120px", + "160px", "100px", "120px", "120px", "130px", "120px", "130px", "200px" + ]} + shrinkZero + /> + } + > + <AvlDetailTableWrapper + promises={promises} + avlListId={Number(id)} + avlListInfo={avlListInfo} + /> + </React.Suspense> + </div> + </div> + </div> + ) +} + +// 실제 데이터를 받아서 AvlDetailTable에 전달하는 컴포넌트 +function AvlDetailTableWrapper({ + promises, + avlListId, + avlListInfo +}: { + promises: Promise<any> + avlListId: number + avlListInfo: any +}) { + const [{ data, pageCount }] = React.use(promises) + + // AVL 타입 결정 + const avlType = avlListInfo.isTemplate ? '선종별표준AVL' : '프로젝트AVL' + + // 선주명 추출 (프로젝트 정보에서) + const shipOwnerName = avlListInfo.shipOwnerName || undefined + + return ( + <AvlDetailTable + data={data} + pageCount={pageCount} + avlListId={avlListId} + avlType={avlType} + projectCode={avlListInfo.projectCode} + shipOwnerName={shipOwnerName} + businessType={avlListInfo.constructionSector || '조선'} + /> + ) +} |
